home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 July / Macworld (1999-07).dmg / Shareware World / Info / For Developers / Mops 3.4.sea / Mops source / PPC source / pnuc4 < prev    next >
Text File  |  1999-02-05  |  18KB  |  708 lines

  1.  
  2. \            ==================================
  3. \                    DICTIONARY LOOKUP
  4. \            ==================================
  5.  
  6.  
  7. : THREAD  ( str-addr -- thread-addr )
  8.     c@ 7 and 2 <<  context +  ;
  9.  
  10.  
  11. : (FIND)  { string-addr lfa
  12.             \ 1st_wd dic-addr str-addr n mismatch? mask flag_byte
  13.               -- xt flag | -- string-addr false }
  14.  
  15. \ lfa points to the dictionary entry where the search is to start.
  16.  
  17. \ first we do a fast check on the length byte and first 3 bytes, then, if
  18. \ this succeeds, we check the full length, 4 bytes at a time.  Note names
  19. \ are always aligned and padded out to a 4-byte boundary with zeros.
  20.  
  21.     $ 1fffffff -> mask
  22.     string-addr @  mask and  -> 1st_wd
  23.  
  24.     BEGIN
  25.         lfa 4+ -> dic-addr
  26.         dic-addr @  1st_wd xor  mask and
  27.         NIF                \ 1st wds match - do full-length check, using
  28.                         \  the string length (as the dic entry may have
  29.                         \  the $20 bit set, which we're ignoring on the
  30.                         \  68k).
  31.             string-addr c@  $ 3F and
  32.             2 >> -> n
  33.             false -> mismatch?
  34.             string-addr -> str-addr
  35.             dic-addr c@  -> flag_byte
  36.             BEGIN
  37.             n WHILE
  38.                 4 ++> str-addr  4 ++> dic-addr
  39.                 str-addr @  dic-addr @ =
  40.                 NIF            \ mismatch - bail out of inner loop and
  41.                             \  return to main loop
  42.                     true -> mismatch?  1 -> n
  43.                 THEN
  44.                 1 --> n
  45.             REPEAT
  46.             mismatch?
  47.             NIF            \ found!
  48.                 dic-addr 6 +              \ return xt
  49.                 flag_byte  $ 40 and
  50.                 IF  1  ELSE  -1  THEN    \ and flag (1 immed, -1 non-immed)
  51.                 EXIT
  52.             THEN
  53.         THEN
  54.  
  55.         lfa @ dup
  56.         NIF            \ failed
  57.             drop  string-addr false  EXIT
  58.         ELSE
  59.             ++> lfa
  60.         THEN
  61.     AGAIN
  62. ;
  63.  
  64. forward  initFind
  65.  
  66. :f initFind  false  ;f
  67.  
  68. : FIND  ( str-addr -- xt flag  |  str-addr -- false )
  69.  
  70.     initFind  ?dup  ?EXIT
  71.     <'> extraFind 2+ @abs @
  72.     IF            \ extraFind has a non-default action set - let's execute it:
  73.         extraFind    ?dup  ?EXIT
  74.     THEN
  75.     dup thread displace
  76.     (find)
  77. ;
  78.  
  79. (*    (findM)  is the lowest-level routine to search through the linked-list of
  80.     methods/ivars for the given selector.
  81.  
  82.     We also set meth_seg# to the seg# of a found method, which helps us
  83.     set the module base registers properly if the method is in a module.
  84.     We don't worry about what we leave in meth_seg# if we don't find the 
  85.     method, or if we're looking for an ivar, so we shouldn't ever rely
  86.     on it in these cases.
  87.  
  88.  
  89.     We put the class offset constants here, since we need some for (findM):
  90.     Note that these MUST AGREE with the definitions in qpClass and zClass!
  91. *)
  92.  
  93. : MFA_offset  ( selID ^class -- selID ^class MFA_offset )
  94.     over
  95.     dup 5 >> +
  96.     $ 1C and  2 +  ;
  97.  
  98. 34    constant    IFA_offset
  99.  
  100. : FFA    inline{ }    ;                \ Flags
  101.  
  102. : MFA  ( SelID ^Class -- SelID MFA )  inline{ MFA_offset +}  ;
  103.  
  104. : IFA    inline{ IFA_offset +}  ;    \ ivar link
  105. : DFA    inline{ 40 +}  ;            \ Data len (2 bytes),
  106.                                     \  width of indexed elts (2 bytes)
  107. : XOFFA    inline{ 44 +}  ;            \ indexing offset for large_obj_arrays
  108. : SFA    inline{ 46 +}  ;            \ Superclass N-way pointer
  109.  
  110. 46    constant    classSize            \ total size of class info up to N-way
  111.  
  112.  
  113.  
  114. 0    value    methSearch?
  115. 0    value    selfRef?
  116. 0    value    sch_offset
  117. 0    value    sch_selID
  118. 0    value    searchedClass
  119.  
  120. 0    value    findmTest?
  121.  
  122. forward  sch_in_class
  123.  
  124. : search_superclasses  { ^n-way \ supOffs ^class hdlr svHeldMod svHMS HMsaved?
  125.                         -- offs ^meth/ivar T | -- F }
  126.  
  127.     0  -> supOffs            \ initial base offset
  128.     false -> HMsaved?        \ not saving heldMod yet
  129.     BEGIN
  130.         ^n-way @ NIF  false  EXIT  THEN        \ end of n-way - search failed
  131.         ^n-way @abs -> ^class                \ get the superclass
  132.  
  133.         sups2skip                            \ are we to skip this superclass?
  134.         IF                                    \ yes - decrement skip count and skip it
  135.             -1 ++> sups2skip
  136.         ELSE                                \ no - we do the search:
  137.  
  138.             last_RP_seg# dup -> meth_seg#    \ in case we find the method here
  139.  
  140.     (* First, we may need to save heldMod and heldModStart over the recursive
  141.         call.  We only need to do this if:
  142.         
  143.         1. The class is in the main dic, and we're in a module.
  144.         2. The class is in a module, and we're either in the main
  145.             dic or in a different module.
  146.  
  147.         So what we do, is check if we're in a module and the class is
  148.         in the SAME module, since this is easy to check for, and in
  149.         all other cases save heldMod and clear it.  If we're in the
  150.         main dic and the class is in the main dic, we'll be saving
  151.         and restoring unnecessarily, but it's harmless, and anyway
  152.         we don't know if we're going into a module until we call
  153.         ?>classInMod.
  154.     *)
  155.  
  156.     ( last_RP_seg# ) 9 >  heldMod and        \ true iff we're in a mod and the
  157.                                             \  class is in the SAME module
  158.             NIF
  159.                 heldMod -> svHeldMod        \ save heldMod and heldModStart
  160.                 heldModStart -> svHMS
  161.                 true -> HMsaved?
  162.                 0 -> heldMod                \ will be set by ?>classInMod if we go
  163.                                             \  into a module, otherwise it will
  164.                                             \  stay zero
  165.                 ^class ?>classInMod -> ^class
  166.                                     \ if class is exported, go into the module
  167.                 heldMod ?dup IF  4+ w@  -> meth_seg#  THEN
  168.     \            seg#_accessed ?dup IF  -> meth_seg#  THEN
  169.                                     \ and if we did, set meth_seg# to the seg#
  170.                                     \  in case we find the method there
  171.             THEN
  172.  
  173.             ^class sch_in_class                \ search the class
  174.  
  175.             IF                                \ found!
  176.                 swap supOffs + swap            \ update offs by whatever
  177.                                             \  sch_in_class returned
  178.  
  179.     \ We don't restore any saved heldMod value in this case.
  180.     \ ** special note: here in the 68k version we unhold any saved heldMod,
  181.     \  after checking if it's different to the one the search succeeded in.
  182.     \ But now we're never unlocking modules, so I'm omitting this, to keep
  183.     \ things a bit simpler.
  184.  
  185.                 true  EXIT
  186.  
  187.             ELSE                            \ search failed in that class
  188.                 HMsaved?
  189.                 IF
  190.                     ?unHoldMod                \ unhold the mod we just searched in
  191.                     svHeldMod -> heldMod    \ and restore heldMod etc.
  192.                     svHMS -> heldModStart
  193.                 THEN
  194.             THEN
  195.         THEN
  196.  
  197.         ^class DFA w@  #align 4+
  198.         ++> supOffs            \ not found - update offset by ivar len of that
  199.                             \  superclass, plus alignment and the 2 2-byte
  200.                             \  offsets we put between embedded objects
  201.                             \  (^class and indexed area offsets)
  202.         4 ++> ^n-way
  203.     AGAIN  ;
  204.  
  205.  
  206. :f sch_in_class  { ^class \ addr selID -- offs ^meth/ivar T | -- F }
  207.  
  208.     ^class -> searchedClass                \ we need this in a few places
  209.     ^class  sch_offset +  -> addr        \ head of linked list for search
  210.     BEGIN
  211. \        addr @ NIF  false  EXIT  THEN    \ zero link - search failed
  212. \        addr displace -> addr            \ follow link
  213.  
  214.         addr @ dup 0EXIT
  215.         ++> addr
  216.  
  217.         addr @ -> selID
  218.         selID 0>
  219.         IF                \ positive - so it's an n-way, not a selID at all
  220.             addr  ( ^n-way ) search_superclasses  EXIT
  221.         THEN
  222.  
  223.         selID sch_selID =
  224.         IF                    \ may be a match - but if a method,
  225.                             \  we have to check if it's private
  226.             methSearch?
  227.             IF    addr 8 + w@        \ get the flags
  228.                 1 and not        \ it's a match if it's public (bit is zero)
  229.                 selfref? or        \ or a reference to self or super
  230.                 dup
  231.                 IF    14 ++> addr  THEN    \ update addr to 'xt' of method
  232.             ELSE
  233.                 true            \ ivar search - it's a match no matter what,
  234.                                 \  and we return the addr of the start of the
  235.                                 \  ivar's info.
  236.     \            4 ++> addr        \ update addr to class pointer
  237.             THEN
  238.         ( match? )
  239.             IF                    \ found!
  240.                 0                \ always return zero offset from non-MI search
  241.                 addr            \ addr of matching meth/ivar
  242.                 true  EXIT
  243.             THEN
  244.         THEN
  245.         
  246.         4 ++> addr                \ no match yet - look at next link
  247.     AGAIN
  248. ;f
  249.  
  250.  
  251. : (findM)  ( selID ^class search_offset methSearch? -- offs ^mcfa true | false )
  252.     -> methsearch?
  253.     -> sch_offset
  254.     swap -> sch_selID
  255.  
  256. (*    Now before we start the search, we have to initialize meth_seg# in case
  257.     we find the method straight away.  last_RP_seg# will be the seg# of the
  258.     current class, since the caller will have just done @abs on the reloc
  259.     pointer to the class.  But if the class is exported, last_RP_seg# will
  260.     refer to the exported entry, not the seg# of the module.  However, in
  261.     this case heldmod will be nonzero, and we can pick up the seg# from
  262.     offset 4 from heldmod.
  263. *)
  264.     
  265.     heldmod
  266.     IF        heldmod 4+ w@
  267.     ELSE    last_RP_seg#
  268.     THEN  -> meth_seg#
  269.  
  270.   ( ^class )  sch_in_class
  271. ;
  272.  
  273.  
  274. : SFIND  ( str-addr len -- xt flag  |  str-addr false )
  275.     pad place
  276.     case_in_names?
  277.     NIF     pad count upper  THEN
  278.     pad find  ;
  279.  
  280.  
  281. :f DEFINED?  ( -- xt flag  |  str-addr false )
  282.     Mword  find  ;f
  283.  
  284.  
  285. \ Note:  ' and ['] are in qpCond, since we still need the 68k versions
  286. \  before then.
  287.  
  288.  
  289.  
  290. \                =============================
  291. \                        COMPILATION
  292. \                =============================
  293.  
  294.  
  295. forward ppc_compile            \ in cg6
  296.  
  297. (*
  298.     (COMP)  ( xt -- )  Compiles the word with the given xt.
  299.     All compilation should be done via this word or (COMPN), since fooling
  300.     the code generator by bypassing it probably isn't a good idea.
  301.     This word assumes a zero opcode is to be passed to the generator.
  302.     If not, use (COMPN).
  303. *)
  304.     
  305. : (COMP)  ( xt -- )
  306.     dup 2- w@  0  ppc_compile  ;
  307.  
  308. \ ANSI synonym:
  309.  
  310. : COMPILE,    (comp)  ;
  311.  
  312.  
  313. \ (COMPN)  ( xt n -- )  is similar to (COMP), but has an additional
  314. \ parameter n which is the opcode for  -> ++>  etc.
  315.  
  316. : (COMPN)  { xt n -- }
  317.     xt dup 2- w@  n  ppc_compile  ;
  318.  
  319.  
  320. \ Interpretation ( EX-GEN etc. ) is in cg7 which is only loaded in PPC
  321. \  mode.  This is because EX-GEN needs :NONAME (at least).
  322.  
  323.  
  324. \                ================================
  325. \                        DEFINING WORDS
  326. \                ================================
  327.  
  328.  
  329. : ((HDR))  { ^newLF \ ^oldLF ^thread -- }
  330.  
  331.     CDP thread
  332.     dup -> ^thread            \ head of thread in CONTEXT
  333.     displace  -> ^oldLF
  334.     ^oldLF ^newLF  displ!
  335.     ^newLF ^thread displ!
  336.  
  337.     CDP dup c@ 1+ #align4  ++> CDP
  338.     $ 80 swap cset
  339. ;
  340.  
  341.  
  342. \ on the 68k we needed to handle both kinds of headers, but only one on the
  343. \  PPC.  Also, we used to vector HEADER, in case we wanted to do something
  344. \  clever, but we never did, so let's not vector it any more.
  345.  
  346. : HEADER  { \ ^newLF -- }
  347.  
  348.     code_align ?dp
  349.     CDP -> ^newLF                \ this will be where the new link field will go
  350.     0 code,
  351.     CDP -> latest
  352.     Mword drop
  353.     ^newLF ((hdr))
  354. ;
  355.     
  356. \ ' (header)  -> header
  357.  
  358. : PPC_HEADER    header  ;
  359.  
  360.  
  361. : SHDR    { addr len \ ^newLF -- }    \ Creates a header for the passed-in string.
  362.  
  363.     code_align
  364.     CDP -> ^newLF                \ this will be where the new link field will go
  365.     0 code,
  366.     CDP -> latest
  367.     addr len CDP place
  368.     CDP count upper
  369.     ^newLF ((hdr))
  370. ;
  371.  
  372.  
  373. : (hr)  ( nfa link -- )
  374.     swap thread
  375.     tuck -  swap !  ;
  376.  
  377.  
  378. : HIDE    \ ( -- )  Hides the name of the current definition from dic searches.
  379.     latest
  380.     dup n>link  displace
  381.     (hr)  ;        immediate
  382.  
  383.  
  384. : REVEAL \ ( -- )  Makes the current name visible again.
  385.     latest
  386.     dup n>link
  387.     (hr)  ;        immediate
  388.  
  389.  
  390. : COLHDR    \ ( -- )  Lays down the header for a colon definition.
  391.     header
  392.     $ BE00  codeW,  ;
  393.  
  394.  
  395. \            =================================
  396. \                    STACK DUMPING, ETC.
  397. \            =================================
  398.  
  399. : .val
  400.     .r  2 spaces  ;
  401.  
  402. ' null    vect    sPrint
  403.  
  404.  
  405. : NAME?    \ ( addr -- addr b )
  406.     dup >name n>count
  407.     + #align4 2+ over =  ;
  408.  
  409.  
  410. : XT?  { xt \ code -- xt b }    \  Checks if xt is really a legal xt.
  411.     xt                                    \ we'll return this
  412.     xt 2- 3 and  IF false EXIT  THEN    \ 2 less must be aligned
  413.     xt 2- c@ -> code                    \ top byte of handler
  414.     code $ BD =  code $ BE = or
  415. ;
  416.  
  417. : ?XT    \ ( xt -- xt )
  418.     xt? NIF     ." not a valid xt" 1 die  THEN
  419. ;
  420.  
  421.  
  422. : aligned_addr?        \ ( ?addr -- ?addr b )
  423.         \ Checks if ?addr could really be an aligned address.  Used in stack
  424.         \  dumping when we don't know what a value is, but want to print a
  425.         \  name if there is one.  We have to apply this check first so that
  426.         \  we don't get an "unmapped address" error.
  427.  
  428.     dup 2+ $ FFFFFFFC and  NIF  false  EXIT  THEN
  429.     dup    $ F0000000 and   IF  false  EXIT  THEN
  430.     true
  431. ;
  432.  
  433.  
  434. : .ID    \ ( ?xt -- )
  435.     aligned_addr?     NIF  drop  EXIT  THEN
  436.     name?    NIF     drop  ." (no name)"  EXIT  THEN
  437.     >name n>count  type
  438. ;
  439.  
  440.  
  441. : CLASS?    \ ( ?xt -- ?xt b )  Returns true if ?xt refers to a class.
  442.     dup 2- w@
  443.     dup $ BC1D =    if  drop true  EXIT  then    \ class_h
  444.         $ BC2D =    if         true  EXIT  then    \ class_in_mod_h
  445.     false
  446. ;
  447.  
  448. : CHKCLASS    \ ( xt -- xt )
  449.     class?  ?EXIT
  450.     .id  space  80 die  ;
  451.  
  452.  
  453. 0        value    theObj
  454. true    value    gotoMod?
  455.  
  456. : >classRP { ^obj \ ^class tmp -- ^classRP | -- 0 }
  457.  
  458. (*    Takes an object address and returns the address of the reloc pointer
  459.     to the class (which will be somewhere in front of the object's data).
  460.     Returns zero if the passed-in address isn't an object address.
  461.     Needs to work for heap as well as dictionary objects.  The test is very
  462.     unlikely (maybe 1/2**24) to indicate a non-object as being an object.
  463.     To save time we don't do a conservative check on ^obj actually being a 
  464.     legal address (unlike ALIGNED_ADDR?), apart from checking that it is aligned,
  465.     which is a very quick check.  This means we may crash if an aligned but 
  466.     illegal address is passed in.  The presumption is that it really is an 
  467.     object address, and that anything else is a comparatively unlikely error.
  468. *)
  469.     false                            \ guilty until proven innocent
  470.     ^obj 3 and              ?EXIT    \ if not aligned, it can't be an obj addr
  471.     ^obj -> theObj                    \ save obj addr in theObj - needed sometimes
  472.     ^obj 4 - w@x -> tmp                \ grab ^class offset
  473.     tmp 3 and                ?EXIT    \  which must be aligned
  474.     tmp $ FF00 and $ FF00 =    0EXIT    \  and must be $FFxx
  475.     ^obj 4 - ++> tmp                \ now tmp points to the reloc class ptr
  476.     drop  tmp                        \ which is what we return
  477. ;
  478.  
  479. : classRP>class  { ^classRP -- ^class | -- 0 }
  480.         \ Takes the address of a class reloc pointer, and returns the
  481.         \  real class address, going into a module if necessary.
  482.         \ Returns zero if the reloc pointer doesn't point to a class.
  483.  
  484.     ^classRP @abs  class?
  485.     NIF  drop 0  EXIT  THEN        \ if not a class, orig addr wasn't an obj addr                        \ drop false flag
  486.  
  487.     gotoMod?
  488.     IF    ?>classInMod
  489.     ELSE
  490.         true -> gotoMod?
  491.     THEN
  492. ;
  493.  
  494.  
  495. : >CLASS  { ^obj \ ^class tmp -- ^class | -- 0 }
  496.  
  497. (*    Converts an object address to its class address, going into a module if
  498.     necessary.  Returns zero if the passed-in address isn't an object address.
  499.     For other comments, see >classRP.
  500. *)
  501.  
  502.     ^obj >classRP  dup  0EXIT        \ out with zero if not a legal object
  503.     classRP>class
  504. ;
  505.  
  506.  
  507. : >CLASS  { ^obj \ ^class tmp -- ^class | -- 0 }
  508.  
  509. (* Converts an object address to its class address.  Returns zero if the passed-in
  510.   address isn't an object address.  Needs to work for heap as well as dictionary
  511.   objects.  The test is very unlikely (maybe 1/2**24) to
  512.   indicate a non-object as being an object.  Without tagged storage we can't
  513.   be absolutely sure.  To save time we don't do a conservative check on ^obj
  514.   actually being a legal address (unlike aligned_addr?), apart from checking that 
  515.   it is aligned, which is a very quick check.  This means we may crash if an
  516.   aligned but illegal address is passed in.  The presumption is that it really is 
  517.   an object address, and that anything else is an (unlikely) error.
  518. *)
  519.     false                            \ guilty until proven innocent
  520.     ^obj 3 and              ?EXIT    \ if not aligned, it can't be an obj addr
  521.     ^obj -> theObj                    \ save obj addr in theObj - needed sometimes
  522.     ^obj 4- w@x -> tmp                \ grab ^class offset
  523.     tmp  3 and                ?EXIT    \  which must be aligned
  524.     tmp $ FF00 and $ FF00 =    0EXIT    \  and must be $FFxx
  525.     ^obj 4- ++> tmp                    \ now tmp points to the class ptr (reloc)
  526.     tmp @abs  class?
  527.     NIF drop  EXIT  THEN            \ if not a class, orig addr wasn't an obj addr
  528.     -> ^class
  529.     gotoMod?
  530.     IF ^class ?>classInMod -> ^class
  531.     ELSE
  532.         true -> gotoMod?
  533.     THEN
  534.     drop ^class
  535. ;
  536.  
  537.  
  538. : >CLASSXT        \ ( ^obj -- ^class | -- 0 )
  539.  
  540. (* As for >CLASS, but if the class is exported from a module and
  541.   you are executing in the main dictionary, it gives the cfa of
  542.   the imported word, without accessing the module.  This can be useful
  543.   if you just want to identify a class without needing all the class info.
  544.   If you are executing in the module, however, you will get the cfa of
  545.   the class in the module.  The general rule is that the returned cfa will
  546.   always be the same as if you had just ticked the classname, wherever you
  547.   are executing.  As for >CLASS, zero is returned if the passed-in address
  548.   doesn't point to an object.
  549. *)
  550.     false -> gotoMod?  >class
  551. ;
  552.  
  553.  
  554. : OBJ?        \ ( ?^obj -- ?^obj ^class  |  -- ?^obj 0 )
  555.  
  556. (* General test for an object.  Not completely rigorous, so we
  557.   shouldn't use it in a TRAV, but pretty good nevertheless.  If it is
  558.   an object, the class is returned, otherwise zero.  We do assume
  559.   the passed-in value may not be a legal address at all, since we want
  560.   to use this word in stack dumping.
  561. *)
  562.     aligned_addr? NIF  0  EXIT  THEN
  563.     dup >class
  564. ;
  565.  
  566.  
  567. 0    value    the_xt
  568.  
  569. : RA?  { addr \ instrn -- b }
  570.             \ Returns true if the addr looks like a return addr.  In this
  571.             \ case it leaves the xt of the branch target in the_xt.
  572.  
  573.     addr $ FFFFFFFC and  NIF  false  EXIT  THEN
  574.     addr $ F0000000 and   IF  false  EXIT  THEN
  575.                         \ so we don't get an unmapped addr when we do @
  576.  
  577. \ OK, it's aligned.  If there's a bl instrn 4 bytes back from that
  578. \  address, it's very likely to be a return addr.
  579.  
  580.     addr 4- @  -> instrn
  581.     instrn  $ FC000001 and  $ 48000001 =  NIF  false  EXIT  THEN
  582.     instrn 6 << 6 a>> $ FFFFFFFC and
  583.     addr 4- + 2-  -> the_xt
  584.     true
  585. ;
  586.  
  587.  
  588. :f .objOrRA        \ ( addr -- )
  589.     obj?  dup
  590.     NIF        \ not an obj - check for return addr
  591.         drop
  592.         RA?  0EXIT
  593.         the_xt .id
  594.     ELSE        \ ( ^obj ^class )
  595.         swap 12 - (@abs)  dup
  596.         IF        .id
  597.         ELSE    drop  ." (no name)"
  598.         THEN
  599.         ."     class:  "  .id
  600.     THEN
  601. ;f
  602.  
  603.  
  604. :f (.stk)  { start-addr end-addr chkForRA? \ svBase val dpth cnt -- }
  605.  
  606.     base -> svBase
  607.     0 -> out  0 -> cnt
  608.     
  609.     start-addr end-addr >
  610.     IF    ."  underflow"    cr EXIT  THEN
  611.     start-addr end-addr =
  612.     IF    ."  empty"        cr EXIT  THEN
  613.  
  614.     end-addr start-addr - 4/  -> dpth
  615.     ."  depth "  dpth .
  616.     .stk_limit dpth min 4*  start-addr +  -> end-addr
  617.  
  618.     BEGIN
  619.         ?pause  cr
  620.         fWind?
  621.         IF    cnt  16 >= if dbgr 0 -> cnt  else  1 ++> cnt  then
  622.         THEN
  623.         10 -> base
  624.         start-addr @ -> val
  625.         val 8 .val
  626.         16 -> base
  627.         & $ emit  val 6 .r
  628.         chkForRA? IF  space  val .objOrRA  3 spaces  THEN
  629.  
  630.         4 ++> start-addr
  631.         start-addr end-addr >=
  632.     UNTIL
  633.     svBase -> base  cr
  634. ;f
  635.  
  636.  
  637. :f .S
  638.     -curs
  639.     ." Stack:"
  640.     sp@ sp0  false  (.stk)
  641. ;f
  642.  
  643.  
  644. : .SEGS  { \ ^entry BA len flags --  seg# displ }
  645.     max_segs 0
  646.     DO    i  8 *  segTable +  -> ^entry
  647.         ^entry @ dup $ 00ffffff and -> len  24 >> -> flags
  648.         len
  649.         IF                        \ something there
  650.             i 8 + . cr
  651.             ^entry 4+ @ -> BA
  652.             BA nilP =
  653.             IF    ." absent"
  654.             ELSE
  655.                 BA .h  ."   len "  len .h
  656.             THEN
  657.             ."   flags "  flags .h  cr
  658.         THEN
  659.     LOOP
  660. ;
  661.  
  662.  
  663. endload
  664.  
  665. \    TESTING:
  666.  
  667. (* ***
  668. dummycl META
  669.  
  670.  
  671. :class OBJECT super{ meta }
  672. :m aa: 1 2 3 ;m
  673. :m bb: 99 aa: self  ;m
  674. ;class
  675.  
  676.  
  677. :class cl2 super{ object }
  678.   object bloggs
  679. :m cc:  $ 1234  bb: bloggs
  680. ;m
  681. ;class
  682.  
  683.  
  684. cl2  myObj
  685.  
  686. *** *)
  687.  
  688. :f RUN { \ x -- }
  689.  
  690. dbgr
  691.     cr cr  1 2 3 4  .s cr
  692.     begin
  693.         query cr
  694.         begin
  695.             rest nip 0>
  696.         while
  697.             defined? 
  698.             if        execute
  699.             else     number  
  700.             then
  701.         repeat
  702.         .s cr
  703.     again
  704. ;f
  705.  
  706. :f quit  run  ;f        \ temp so we can catch errors!
  707.  
  708.